package com.example.security.jwt.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.core.GrantedAuthorityDefaults;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;

import com.example.security.jwt.filter.JwtLoginFilter;
import com.example.security.jwt.filter.JwtVerifyFilter;

/**
 * 统一配置.
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	
	@Autowired
	private UserDetailsService userService;
	@Autowired
	private AccessDeniedHandler myAccessDeniedHandle;
	@Autowired
	private AuthenticationEntryPoint myAuthenticationEntryPoint;

	@Bean
	public PasswordEncoder myPasswordEncoder() {
		return new BCryptPasswordEncoder();
	}

	/**
	 * Remove the ROLE_ prefix
	 */
	@Bean
	public GrantedAuthorityDefaults grantedAuthorityDefaults() {
		return new GrantedAuthorityDefaults("");
	}

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
				// 允许访问
				.antMatchers("/login").permitAll() // login 不拦截
				.anyRequest().authenticated() // 其他请求拦截
				.and()
				.csrf().disable() // 关闭csrf
				.cors()// 允许跨域
				.and()
				.addFilter(new JwtLoginFilter(super.authenticationManager()))
				.addFilter(new JwtVerifyFilter(super.authenticationManager())).exceptionHandling()
				.accessDeniedHandler(myAccessDeniedHandle) // 自定义无权限访问
				.authenticationEntryPoint(myAuthenticationEntryPoint) // 自定义未登录返回
				.and()
				.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // 禁用session
	}

	@Override
	public void configure(AuthenticationManagerBuilder auth) throws Exception {
		// UserDetailsService类
		auth.userDetailsService(userService)
				// 加密策略
				.passwordEncoder(myPasswordEncoder());
	}

	/**
	 * 解决 AuthenticationManager 无法注入的问题
	 */
	@Bean
	@Override
	public AuthenticationManager authenticationManagerBean() throws Exception {
		return super.authenticationManagerBean();
	}
}
